package cn.tedu.csmall.passport.service.impl;

import cn.tedu.csmall.commons.exception.ServiceException;
import cn.tedu.csmall.passport.mapper.AdminMapper;
import cn.tedu.csmall.passport.mapper.AdminRoleMapper;
import cn.tedu.csmall.passport.pojo.entity.Admin;
import cn.tedu.csmall.passport.pojo.entity.AdminRole;
import cn.tedu.csmall.passport.pojo.param.AdminInsertParam;
import cn.tedu.csmall.passport.pojo.param.AdminLoginInfoParam;
import cn.tedu.csmall.passport.pojo.param.AdminUpdateInfoParam;
import cn.tedu.csmall.passport.pojo.vo.AdminListVO;
import cn.tedu.csmall.passport.pojo.vo.AdminStandardVO;
import cn.tedu.csmall.commons.pojo.vo.PageData;
import cn.tedu.csmall.passport.security.AdminDetails;
import cn.tedu.csmall.passport.service.AdminService;
import cn.tedu.csmall.commons.util.PageDataConverter;
import cn.tedu.csmall.commons.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service

public class AdminServiceImpl implements AdminService {
    @Autowired
    AdminMapper mapper;
    @Autowired
    AdminRoleMapper adminRoleMapper;
    @Autowired
    private AuthenticationManager manager;

    @Value("${csmall.jwt.key}")
    private String key;
    @Value("${csmall.jwt.duration}")
    private Long durationByMinute;

    @Override
    public String login(AdminLoginInfoParam adminLoginInfoParam) {
        Authentication authentication=new UsernamePasswordAuthenticationToken(
                adminLoginInfoParam.getUsername(),
                adminLoginInfoParam.getPassword());

        Authentication authenticate = manager.authenticate(authentication);
        log.debug("验证登录完成，认证结果：{}", authenticate);
        Object principal = authenticate.getPrincipal();
        AdminDetails adminDetails=(AdminDetails)principal;
        //String key="fhjkahfjkdahfjka2365465fjagdjkaddAEDFSD";
        Map<String,Object> claims=new HashMap<>();
        claims.put("id",adminDetails.getId());
        claims.put("username",adminDetails.getUsername());
        claims.put("authorities", JSON.toJSONString(adminDetails.getAuthorities()));
        String jwt = Jwts.builder()
                //Header
                .setHeaderParam("alg","HS256")
                .setHeaderParam("typ","JWT")
                //Payload
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis()+durationByMinute*60*1000))
                //Verify Signature
                .signWith(SignatureAlgorithm.HS256,key)
                //生成
                .compact();
        log.debug("生成了jwt,{}",jwt);
        return jwt;
//        SecurityContext context = SecurityContextHolder.getContext();
//        context.setAuthentication(authenticate);
    }

    @Override
    public void insert(AdminInsertParam adminInsertParam) {
        QueryWrapper<Admin> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("username",adminInsertParam.getUsername());
        int count=mapper.selectCount(queryWrapper);
        if(count>0){
            String message="添加管理员失败，管理员用户名已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }

        QueryWrapper<Admin> queryWrapper2=new QueryWrapper<>();
        queryWrapper2.eq("phone",adminInsertParam.getPhone());
        int count2=mapper.selectCount(queryWrapper2);
        if(count2>0){
            String message="添加管理员失败，管理员手机号已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }

        QueryWrapper<Admin> queryWrapper3=new QueryWrapper<>();
        queryWrapper3.eq("email",adminInsertParam.getEmail());
        int count3=mapper.selectCount(queryWrapper3);
        if(count3>0){
            String message="添加管理员失败，管理员邮箱已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }


        Admin admin=new Admin();
        BeanUtils.copyProperties(adminInsertParam,admin);
        admin.setLoginCount(0);
        admin.setGmtCreate(LocalDateTime.now());
        admin.setGmtModified(LocalDateTime.now());
        PasswordEncoder encoder=new BCryptPasswordEncoder();
        admin.setPassword(encoder.encode(admin.getPassword()));
        log.debug("准备将新的管理员数据写入到数据库，数据：{}", admin);
        int rows = mapper.insert(admin);
        if(rows!=1){
            String message="添加管理员失败，服务器忙，请稍后再试!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_INSERT);
        }
        log.debug("将新的管理员数据写入到数据库，完成");


        Long[] roleIds=adminInsertParam.getRoleIds();
        AdminRole[] adminRoles=new AdminRole[roleIds.length];
        for (int i = 0; i <adminRoles.length ; i++) {
            AdminRole adminRole=new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRole.setGmtCreate(LocalDateTime.now());
            adminRole.setGmtModified(LocalDateTime.now());
            adminRoles[i]=adminRole;
        }
        int row2 = adminRoleMapper.insertBatch(adminRoles);
        if(row2!=roleIds.length){
            String message="添加管理员失败，服务器忙，请稍后再试!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_INSERT);
        }
        log.debug("将新的管理员与角色关联数据写入到数据库，完成");

    }

    @Override
    public void deleteById(Long id) {
        log.debug("开始处理【根据ID删除管理员】的业务，参数：{}", id);
        // 检查管理员是否存在，如果不存在，则抛出异常
        QueryWrapper<Admin> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("id", id);
        int countById = mapper.selectCount(queryWrapper1);
        log.debug("根据管理员ID统计匹配的管理员数量，结果：{}", countById);
        if (countById == 0) {
            String message = "删除管理员失败，管理员数据不存在！";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_NOT_FOUND);
        }
        //检查是否有角色关联此管理员
        QueryWrapper<AdminRole> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("admin_id",id);
        int countByAdminId = adminRoleMapper.selectCount(queryWrapper);
        log.debug("根据管理员名称统计匹配的管理员数量，结果：{}", countByAdminId);
        if(countByAdminId>0){
            adminRoleMapper.deleteByAdminId(id);
        }


        int row = mapper.deleteById(id);
        if(row !=1){
            String message="添加管理员失败，服务器忙，请稍后再试!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_DELETE);
        }
        log.debug("根据ID从数据库中删除，完成！");
    }

    @Override
    public void update(Long id, String password) {
        QueryWrapper<Admin> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("id", id);
        int countById = mapper.selectCount(queryWrapper1);
        if(countById==0){
            String message = "修改管理员失败，管理员数据不存在！";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_NOT_FOUND);
        }
        PasswordEncoder encoder=new BCryptPasswordEncoder();
        password=encoder.encode(password);
        mapper.updatePassword(id,password);
    }

    @Override
    public void update(AdminUpdateInfoParam adminUpdateInfoParam) {
        log.debug("开始处理【修改管理员】的业务，参数：{}", adminUpdateInfoParam);
        QueryWrapper<Admin> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("id", adminUpdateInfoParam.getId());
        int countById = mapper.selectCount(queryWrapper1);
        log.debug("根据管理员ID统计匹配的管理员数量，结果：{}", countById);
        if (countById == 0) {
            String message = "修改管理员失败，管理员数据不存在！";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_NOT_FOUND);
        }

        QueryWrapper<Admin> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("username",adminUpdateInfoParam.getUsername())
                .ne("id",adminUpdateInfoParam.getId());
        int countByName = mapper.selectCount(queryWrapper);
        log.debug("根据管理员名称统计匹配的管理员数量，结果：{}", countByName);
        if(mapper.selectCount(queryWrapper)>0){
            String message="修改管理员失败，管理员用户名已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }
        QueryWrapper<Admin> queryWrapper2=new QueryWrapper<>();
        queryWrapper2.eq("phone",adminUpdateInfoParam.getPhone())
                .ne("id",adminUpdateInfoParam.getId());
        int countByPhone = mapper.selectCount(queryWrapper2);
        log.debug("根据管理员名称统计匹配的管理员数量，结果：{}", countByPhone);
        if(countByPhone>0){
            String message="修改管理员失败，管理员手机号已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }

        QueryWrapper<Admin> queryWrapper3=new QueryWrapper<>();
        queryWrapper3.eq("email",adminUpdateInfoParam.getEmail())
                .ne("id",adminUpdateInfoParam.getId());
        int countByEmail = mapper.selectCount(queryWrapper3);
        log.debug("根据管理员名称统计匹配的管理员数量，结果：{}", countByEmail);
        if(countByEmail>0){
            String message="修改管理员失败，管理员邮箱已被占用!";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_CONFLICT);
        }
        //执行修改
        Admin admin=new Admin();
        BeanUtils.copyProperties(adminUpdateInfoParam,admin);
        int row = mapper.updateById(admin);
        if(row !=1){
            String message="添加管理员失败，服务器忙，请稍后再试!";
            log.warn(message);
            throw new ServiceException(message, ServiceCode.ERR_UPDATE);
        }
        log.debug("根据ID从数据库中修改，完成！");
    }
    
    @Override
    public AdminStandardVO getStandardById(Long id) {
        log.debug("开始处理【根据ID查询管理员详情】的业务，参数：{}", id);
        AdminStandardVO standardById = mapper.getStandardById(id);
        if(standardById==null){
            String message = "查询管理员详情失败，管理员数据不存在！";
            log.warn(message);
            throw new ServiceException(message,ServiceCode.ERR_NOT_FOUND);
        }
        return mapper.getStandardById(id);
    }

    @Override
    public PageData<AdminListVO> list(Integer pageNum) {
        Integer pageSize=5;
        return list(pageNum,pageSize);
    }

    @Override
    public PageData<AdminListVO> list(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Admin> list = mapper.list();
        PageInfo pageInfo=new PageInfo(list);
        PageData pageData= PageDataConverter.convert(pageInfo);
        return pageData;
    }
}
